package com.ly.system.controller;

import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ly.common.core.bean.R;
import com.ly.common.core.bean.dto.EnableDTO;
import com.ly.common.core.constant.BaseConstant;
import com.ly.common.core.constant.TokenConstants;
import com.ly.common.core.utils.BaseUtils;
import com.ly.common.core.utils.CommonUtils;
import com.ly.common.core.utils.RedisUtils;
import com.ly.common.core.utils.excel.ExcelResult;
import com.ly.common.core.utils.excel.ExcelUtil;
import com.ly.system.system.bean.dto.AppDTO;
import com.ly.system.system.bean.dto.LoginDTO;
import com.ly.system.system.bean.entity.SysDept;
import com.ly.system.system.bean.entity.SysUser;
import com.ly.system.system.bean.entity.SysUserRole;
import com.ly.system.system.bean.model.UserDeptVO;
import com.ly.system.system.bean.vo.SysUserRoleVO;
import com.ly.system.service.ISysDeptService;
import com.ly.system.service.ISysUserRoleService;
import com.ly.system.service.ISysUserService;
import io.swagger.v3.oas.annotations.Operation;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.*;

/**
 * 用户
 *
 * @author luoyun
 */
@Slf4j
@RestController
@RequestMapping("/sys/user")
@RequiredArgsConstructor
public class SysUserController {

    private final ISysUserService sysUserService;
    private final ISysDeptService sysDepartService;
    private final ISysUserRoleService sysUserRoleService;
    private final RedisUtils redisUtil;

    @GetMapping("/getId")
    public R<SysUser> getId(@RequestParam(name = "id") String id) {
        return sysUserService.getId(id);
    }

    /**
     * 分页-租户隔离
     *
     * @param entity
     * @param pageNo
     * @param pageSize
     * @return
     */
    @GetMapping("/getPage")
    public R<IPage<SysUser>> getPage(SysUser entity,
                                     @RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo,
                                     @RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize) {
        return sysUserService.getPage(entity, new Page<>(pageNo, pageSize));
    }

    /**
     * 新增
     *
     * @param entity
     * @return
     */
    @PostMapping("/add")
    public R<String> add(@RequestBody SysUser entity) {
        return sysUserService.add(entity);
    }

    /**
     * 修改
     *
     * @param entity
     * @return
     */
    @PostMapping("/edit")
    public R<String> edit(@RequestBody SysUser entity) {
        return sysUserService.edit(entity);
    }

    /**
     * 删除-id
     */
    @DeleteMapping("/delete")
    public R<String> delete(@RequestParam(name = "id") String id) {
        return sysUserService.delete(id);
    }

    /**
     * 批量删除
     */
    @DeleteMapping("/deleteBatch")
    public R<String> deleteBatch(@RequestParam(name = "ids") String ids) {
        return sysUserService.deleteBatch(ids);
    }

    /**
     * 当前用户
     *
     * @return
     */
    @GetMapping("/getCurrentUserData")
    public R<SysUser> getCurrentUserData() {
        return sysUserService.getCurrentUserData();
    }

    /**
     * 冻结&解冻用户
     *
     * @param dto
     * @return
     */
    @PutMapping("/updateStatus")
    public R<String> updateStatus(@RequestBody EnableDTO dto) {
        return sysUserService.updateStatus(dto);
    }

    /**
     * 查询用户角色列表
     *
     * @param userid
     * @return
     */
    @GetMapping("/getRoleByUserId")
    public R<List<String>> getRoleByUserId(@RequestParam(name = "userid") String userid) {
        return sysUserService.getRoleByUserId(userid);
    }

    /**
     * 查询用户职务列表-id
     *
     * @param userid
     * @return
     */
    @GetMapping("/getPostByUserId")
    public R<List<String>> getPostByUserId(@RequestParam(name = "userid") String userid) {
        return sysUserService.getPostByUserId(userid);
    }

    /**
     * 校验用户账号是否唯一<br>
     * 可以校验其他 需要检验什么就传什么。。。
     *
     * @param sysUser
     * @return
     */
    @GetMapping("/checkOnlyUser")
    public R<?> checkOnlyUser(SysUser sysUser) {
        sysUser.setPassword(null);
        SysUser user = sysUserService.getOne(new QueryWrapper<SysUser>(sysUser));
        if (user != null) {
            return R.fail("用户账号已存在");
        }
        return R.ok();
    }

    /**
     * 生成在添加用户情况下没有主键的问题,返回给前端,根据该id绑定部门数据
     *
     * @return
     */
    @GetMapping("/generateUserId")
    public R<String> generateUserId() {
        String userId = UUID.randomUUID().toString().replace("-", "");
        return R.ok(userId);
    }

    /**
     * 导出excel
     *
     * @param response
     */
    @Operation(summary = "导出excel")
    @GetMapping("/exportXls")
    public void exportXls(HttpServletResponse response) {
        List<SysUser> list = sysUserService.list();
        ExcelUtil.exportExcel(list, "工作系数表", SysUser.class, response);
    }

    /**
     * 导入excel
     *
     * @param file
     * @param updateSupport：是否删除标识
     * @return
     */
    @Operation(summary = "导入excel")
    @PostMapping("/importExcel")
    public R<?> importWork(MultipartFile file, boolean updateSupport) throws Exception {
        // 监听： new ImportListener(updateSupport);
        ExcelResult<SysUser> result = ExcelUtil.importExcel(file.getInputStream(), SysUser.class, null);
        return R.ok(true, result.getAnalysis());
    }

    /**
     * 首页用户重置密码
     */
    @PutMapping("/updatePassword")
    public R<String> updatePassword(@RequestBody LoginDTO dto) {
        return sysUserService.updatePassword(dto);
    }

    @GetMapping("/userRoleList")
    public R<IPage<SysUser>> userRoleList(
            @RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo,
            @RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize,
            HttpServletRequest req) {
        Page<SysUser> page = new Page<SysUser>(pageNo, pageSize);
        String roleId = req.getParameter("roleId");
        String username = req.getParameter("username");
        IPage<SysUser> pageList = sysUserService.getUserByRoleId(page, roleId, username);
        return R.ok(pageList);
    }

    /**
     * 给指定角色添加用户
     *
     * @param
     * @return
     */
    @PostMapping("/addSysUserRole")
    public R<String> addSysUserRole(@RequestBody SysUserRoleVO sysUserRoleVO) {
        String sysRoleId = sysUserRoleVO.getRoleId();
        for (String sysUserId : sysUserRoleVO.getUserIdList()) {
            SysUserRole sysUserRole = new SysUserRole(sysUserId, sysRoleId);
            SysUserRole one = sysUserRoleService.getOne(
                    new LambdaQueryWrapper<SysUserRole>()
                            .eq(SysUserRole::getRoleId, sysRoleId)
                            .eq(SysUserRole::getUserId, sysUserId)
            );
            if (one == null) {
                sysUserRoleService.save(sysUserRole);
            }
        }
        return R.ok("添加成功!");
    }

    /**
     * 删除指定角色的用户关系
     *
     * @param
     * @return
     */
    @DeleteMapping("/deleteUserRole")
    public R<String> deleteUserRole(@RequestParam(name = "roleId") String roleId, @RequestParam(name = "userId") String userId) {
        sysUserRoleService.remove(
                new LambdaQueryWrapper<SysUserRole>()
                        .eq(SysUserRole::getRoleId, roleId)
                        .eq(SysUserRole::getUserId, userId)
        );
        return R.ok("删除成功!");
    }

    /**
     * 批量删除指定角色的用户关系
     *
     * @param
     * @return
     */
    @DeleteMapping("/deleteUserRoleBatch")
    public R<String> deleteUserRoleBatch(@RequestParam(name = "roleId") String roleId, @RequestParam(name = "userIds") String userIds) {
        sysUserRoleService.remove(
                new LambdaQueryWrapper<SysUserRole>()
                        .eq(SysUserRole::getRoleId, roleId)
                        .in(SysUserRole::getUserId, Arrays.asList(userIds.split(",")))
        );
        return R.ok("删除成功!");
    }

    /**
     * 根据 orgCode 查询用户，包括子部门下的用户
     * 若某个用户包含多个部门，则会显示多条记录，可自行处理成单条记录
     */
    @GetMapping("/getUserByDept")
    public R<IPage<UserDeptVO>> getUserByDept(
            @RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo,
            @RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize,
            @RequestParam(name = "id", required = false) String id) {
        return sysUserService.getUserByDept(id, new Page(pageNo, pageSize));
    }

    /**
     * 查询当前用户的所有部门/当前部门编码
     *
     * @return
     */
    @GetMapping("/getCurrentUserDeparts")
    public R getCurrentUserDeparts() {
        SysDept dept = sysDepartService.getById(BaseUtils.getDeptId());
        Map<String, Object> map = new HashMap(5);
        List<SysDept> deptList = new ArrayList<>();
        deptList.add(dept);
        map.put("list", deptList);
        map.put("orgCode", BaseUtils.getOrgCode());
        return R.ok(map);
    }

    /**
     * 用户注册接口
     *
     * @param jsonObject
     * @param user
     * @return
     */
    @PostMapping("/register")
    public R<?> userRegister(@RequestBody JSONObject jsonObject, SysUser user) {
        String phone = jsonObject.getString("phone");
        String smscode = jsonObject.getString("smscode");
        String redisKey = BaseConstant.PHONE_REDIS_KEY_PRE + phone;
        Object code = redisUtil.get(redisKey);
        String username = jsonObject.getString("username");
        // 未设置用户名，则用手机号作为用户名
        if (StrUtil.isEmpty(username)) {
            username = phone;
        }
        // 未设置密码，则随机生成一个密码
        String password = jsonObject.getString("password");
        if (StrUtil.isEmpty(password)) {
            password = RandomUtil.randomString(8);
        }
        String email = jsonObject.getString("email");
        SysUser sysUser1 = sysUserService.getUserByName(username);
        if (sysUser1 != null) {
            return R.fail("用户名已注册");
        }
        SysUser sysUser2 = sysUserService.getUserByPhone(phone);
        if (sysUser2 != null) {
            return R.fail("该手机号已注册");
        }
        if (StrUtil.isNotEmpty(email)) {
            SysUser sysUser3 = sysUserService.getUserByEmail(email);
            if (sysUser3 != null) {
                return R.fail("邮箱已被注册");
            }
        }
        if (null == code) {
            return R.fail("手机验证码失效，请重新获取");
        }
        if (!smscode.equals(code.toString())) {
            return R.fail("手机验证码错误");
        }
        String realname = jsonObject.getString("realname");
        if (StrUtil.isEmpty(realname)) {
            realname = username;
        }
        user.setCreateTime(new Date());// 设置创建时间
        String salt = RandomUtil.randomString(TokenConstants.BASE_STR, 8);
        String passwordEncode = CommonUtils.getAesPassWord(username, password, salt);
        user.setSalt(salt);
        user.setUsername(username);
        user.setRealname(realname);
        user.setPassword(passwordEncode);
        user.setEmail(email);
        user.setPhone(phone);
        user.setStatus(BaseConstant.USER_UNFREEZE);
        user.setDelFlag(BaseConstant.DEL_FLAG_0);
        user.setActivitiSync(BaseConstant.ACT_SYNC_1);
        sysUserService.addUserWithRole(user, "");// 默认临时角色 test
        return R.ok("注册成功");
    }

    /**
     * 用户手机号验证
     */
    @PostMapping("/phoneVerification")
    public R<Map<String, String>> phoneVerification(@RequestBody JSONObject jsonObject) {
        String phone = jsonObject.getString("phone");
        String smscode = jsonObject.getString("smscode");
        // update-begin-author:taoyan date:2022-9-13 for: VUEN-2245 【漏洞】发现新漏洞待处理20220906
        String redisKey = BaseConstant.PHONE_REDIS_KEY_PRE + phone;
        Object code = redisUtil.get(redisKey);
        if (!smscode.equals(code)) {
            return R.fail("手机验证码错误");
        }
        // 设置有效时间
        redisUtil.set(redisKey, smscode, 600);
        // update-end-author:taoyan date:2022-9-13 for: VUEN-2245 【漏洞】发现新漏洞待处理20220906
        // 新增查询用户名
        LambdaQueryWrapper<SysUser> query = new LambdaQueryWrapper<>();
        query.eq(SysUser::getPhone, phone);
        SysUser user = sysUserService.getOne(query);
        Map<String, String> map = new HashMap(5);
        map.put("smscode", smscode);
        if (null == user) {
            // 前端根据文字做判断用户是否存在判断，不能修改
            return R.fail("用户信息不存在");
        }
        map.put("username", user.getUsername());
        return R.ok(map);
    }

    /**
     * 用户更改密码
     */
    @GetMapping("/updatePassword4App")
    public R<String> passwordChange(AppDTO dto) {
        return sysUserService.updatePassword4App(dto);
    }

    /**
     * 回收站：正常且未删除
     */
    @Operation(summary = "回收站")
    @GetMapping("/getRecycleUser")
    public R<List<SysUser>> getRecycleUser() {
        return sysUserService.getRecycleUser();
    }

    /**
     * 回收站：还原
     *
     * @param dto
     * @return
     */
    @PutMapping("/putRecycleUser")
    public R putRecycleUser(@Validated @RequestBody EnableDTO dto) {
        return sysUserService.putRecycleUser(dto);
    }

    /**
     * 彻底删除用户
     *
     * @param userIds 被删除的用户ID，多个id用半角逗号分割
     * @return
     */
    @DeleteMapping("/deleteRecycleBin")
    public R<String> deleteRecycleBin(@RequestParam("userIds") String userIds) {
        return sysUserService.removeLogicDeleted(userIds);
    }

    /**
     * 移动端修改用户信息
     *
     * @param jsonObject
     * @return
     */
    @PostMapping("/appEdit")
    public R<?> appEdit(@RequestBody JSONObject jsonObject) {
        String username = BaseUtils.getUsername();
        SysUser sysUser = sysUserService.getUserByName(username);
        String realname = jsonObject.getString("realname");
        String avatar = jsonObject.getString("avatar");
        String sex = jsonObject.getString("sex");
        String phone = jsonObject.getString("phone");
        String email = jsonObject.getString("email");
        Date birthday = jsonObject.getDate("birthday");
        SysUser userPhone = sysUserService.getUserByPhone(phone);
        if (sysUser == null) {
            return R.fail("未找到对应用户!");
        } else {
            if (userPhone != null) {
                String userPhonename = userPhone.getUsername();
                if (!userPhonename.equals(username)) {
                    return R.fail("手机号已存在!");
                }
            }
            if (StrUtil.isNotBlank(realname)) {
                sysUser.setRealname(realname);
            }
            if (StrUtil.isNotBlank(avatar)) {
                sysUser.setAvatar(avatar);
            }
            if (StrUtil.isNotBlank(sex)) {
                sysUser.setSex(Integer.parseInt(sex));
            }
            if (StrUtil.isNotBlank(phone)) {
                sysUser.setPhone(phone);
            }
            if (StrUtil.isNotBlank(email)) {
                // update-begin---author:wangshuai ---date:20220708  for：[VUEN-1528]积木官网邮箱重复，应该提示准确------------
                LambdaQueryWrapper<SysUser> emailQuery = new LambdaQueryWrapper<>();
                emailQuery.eq(SysUser::getEmail, email);
                long count = sysUserService.count(emailQuery);
                if (!email.equals(sysUser.getEmail()) && count != 0) {
                    return R.fail("保存失败，邮箱已存在!");
                }
                // update-end---author:wangshuai ---date:20220708  for：[VUEN-1528]积木官网邮箱重复，应该提示准确--------------
                sysUser.setEmail(email);
            }
            if (null != birthday) {
                sysUser.setBirthday(birthday);
            }
            sysUser.setUpdateTime(new Date());
            sysUserService.updateById(sysUser);
        }
        return R.ok(true, "保存成功");
    }

    /**
     * 根据用户名修改手机号[该方法未使用]
     *
     * @param json
     * @return
     */
    @PutMapping("/updateMobile")
    public R<?> changMobile(@RequestBody JSONObject json, HttpServletRequest request) {
        String smscode = json.getString("smscode");
        String phone = json.getString("phone");
        // 获取登录用户名
        String username = BaseUtils.getUsername();
        if (StrUtil.isEmpty(username) || StrUtil.isEmpty(smscode) || StrUtil.isEmpty(phone)) {
            return R.fail("修改手机号失败！");
        }
        // update-begin-author:taoyan date:2022-9-13 for: VUEN-2245 【漏洞】发现新漏洞待处理20220906
        String redisKey = BaseConstant.PHONE_REDIS_KEY_PRE + phone;
        Object object = redisUtil.get(redisKey);
        // update-end-author:taoyan date:2022-9-13 for: VUEN-2245 【漏洞】发现新漏洞待处理20220906
        if (null == object) {
            return R.fail("短信验证码失效！");
        }
        if (!smscode.equals(object.toString())) {
            return R.fail("短信验证码不匹配！");
        }
        SysUser user = sysUserService.getUserByName(username);
        if (user == null) {
            return R.fail("用户不存在！");
        }
        user.setPhone(phone);
        sysUserService.updateById(user);
        return R.ok("手机号设置成功!");
    }

    /**
     * 用户编辑(vue3用户设置专用)【低代码应用专用接口】
     *
     * @param sysUser
     * @return
     */
    @PostMapping("/login/setting/userEdit")
    public R<String> userEdit(@RequestBody SysUser sysUser, HttpServletRequest request) {
        String username = BaseUtils.getUsername();
        SysUser user = sysUserService.getById(sysUser.getId());
        if (user == null) {
            return R.fail("未找到该用户数据");
        }
        if (!username.equals(user.getUsername())) {
            return R.fail("只能修改自己的数据");
        }
        sysUserService.updateById(sysUser);
        return R.ok("更新个人信息成功");
    }

    /**
     * 更改手机号（敲敲云个人设置专用）
     *
     * @param dto
     */
    @PutMapping("/changePhone")
    public R<String> changePhone(@RequestBody AppDTO dto) {
        return sysUserService.changePhone(dto);
    }
}
